from jose import jwt,JWTError
from typing import Union
from .redis import RedisUtils
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi import Header
from app.config.jwt import Settings,TokenData
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm,OAuth2AuthorizationCodeBearer
from datetime import datetime, timedelta, timezone

async def get_auth_data(authorization: str = Header(None)):
    """
    获取登录用户认证数据, 通常用于controller层
    :param authorization: 请求header中的authorization
    :return:
    """
    return get_auth_data_by_authorization(authorization)


def get_auth_data_by_authorization(authorization: str, ex: int = None):
    """
    获取登录用户认证数据
    :param authorization:
    :param prefix: 前缀
    :param ex: 数据过期秒数
    :return:
    """
    if authorization:
        return get_auth_data_by_token(authorization, ex)

    return None


def get_auth_data_by_token(token: str, ex: int = None):
    """
    获取登录用户认证数据， 从redis中读取
    :param token: 登录的token
    :param ex: 数据过期秒数
    :return: 登录认证数据
    """

    auth_data = RedisUtils().get('token:' + token)

    if ex and auth_data:
        RedisUtils().expire('token:' + token, ex)

    return auth_data


def update_auth_data(auth_data: dict, ex: int = None):
    """
    更新认证数据
    :param auth_data: 登录认证数据
    :param ex: 数据过期秒数
    """
    RedisUtils().set('token:' + auth_data.get('token'), auth_data, ex)


setting=Settings()
# 创建jwt
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_access_token(data: TokenData, expires_delta: Union[timedelta, None] = None):
    print(data)
    to_encode = data.copy()
    
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(days=setting.ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, setting.AUTHJWT_SECRET_KEY, algorithm=setting.ALGORITHM)
    return encoded_jwt

def create_refresh_token(data: TokenData, expires_delta: Union[timedelta, None] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(timezone.utc) + expires_delta
    else:
        expire = datetime.now(timezone.utc) + timedelta(days=setting.REFRESH_TOKEN_EXPIRE_DAYS)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, setting.AUTHJWT_SECRET_KEY, algorithm=setting.ALGORITHM)
    return encoded_jwt

async def get_current_user(token: str = Depends(oauth2_scheme))->TokenData:
    # credentials_exception = HTTPException(
    #     status_code=status.HTTP_401_UNAUTHORIZED,
    #     detail="Could not validate credentials",
    #     headers={"WWW-Authenticate": "Bearer"},
    # )
    # try:
    payload = jwt.decode(token, setting.AUTHJWT_SECRET_KEY, algorithms=[setting.ALGORITHM])
    user_id: str = payload.get("id")
    if user_id is None:
        raise JWTError
    
    token_data = TokenData(**payload)
       
    return token_data

async def get_current_active_user(current_user: str = Depends(get_current_user)):
    print(current_user)
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user